using System;
using System.Collections.Generic;
using System.Text;

namespace FE
{
    public class BattleResult
    {
        const string attackMessage = "{0} attacked {1} and ";
        const string damagesMessage = "does {0} damage.";
        const string evadesMessage = "misses!";
        const string doubledMessage = "{0} double";
        const string critMessage = "{0} critically";
        const string defeatedMessage = " {0} was defeated!";
        //const string attack = "{0} attacked {1} and does {2} damage.";
        public BattleResult(UnitStatus attackerStatus, UnitStatus defenderStatus)
        {
            this.attackerStatus = attackerStatus;
            this.defenderStatus = defenderStatus;
        }
        public override string ToString()
        {

            string message = string.Empty;
            if (critical)
            {
                message = string.Format(critMessage, attackerStatus.unit.Name);
            }
            else
            {
                message = attackerStatus.unit.Name;
            }
            if (doubled)
            {
                message = string.Format(doubledMessage, message);                
            }
            message = string.Format(attackMessage, message, defenderStatus.unit.Name);            
            if (evaded)
            {
                message += evadesMessage;
            }
            else
            {                
                message +=  string.Format(damagesMessage, damage);
            }
            if (killed)
            {
                message += string.Format(defeatedMessage, defenderStatus.unit.Name);
            }
            return message;
        }
        public UnitStatus attackerStatus, defenderStatus;
        public int damage = 0;
        public bool evaded = false;
        public bool critical = false;
        public bool killed = false;
        public bool doubled = false;
    }
    public class Battle
    {
        UnitStatus attackerStatus, defenderStatus;
        public Battle(UnitStatus attackerStatus, UnitStatus defenderStatus)
        {
            this.attackerStatus = attackerStatus;
            this.defenderStatus = defenderStatus;
        }
        public List<BattleResult> GetResults {
            get
            {
                List<BattleResult> results = new List<BattleResult>();
                Unit attacker = attackerStatus.unit;
                Unit defender = defenderStatus.unit;
                int attackProb = attacker.GetHitRate(defender);
                BattleResult r = new BattleResult(attackerStatus, defenderStatus);                    
                if (Game.RNG.Pass(attackProb))
                {
                    int damage = attacker.GetDamage(defender);
                    int critChance = attacker.GetCriticalChance(defender);
                    
                    if (Game.RNG.Pass(critChance))
                    {
                        damage *= 3;
                        r.critical = true;                        
                    }
                    r.damage = damage;
                    defenderStatus.DoDamage(damage);

                    if (defenderStatus.IsDead)
                    {
                        r.killed = true;
                        results.Add(r);
                        return results;
                    }
                }
                else
                {
                    r.evaded = true;                    
                }
                results.Add(r);
                int defendProb = defender.GetHitRate(attacker);
                r = new BattleResult(defenderStatus, attackerStatus);                    
                if (Game.RNG.Pass(defendProb))
                {
                    int damage = defender.GetDamage(attacker);
                    int critChance = defender.GetCriticalChance(attacker);

                    if (Game.RNG.Pass(critChance))
                    {
                        damage *= 3;
                        r.critical = true;                        
                    }
                    r.damage = damage;
                    attackerStatus.DoDamage(damage);

                    if (attackerStatus.IsDead)
                    {
                        r.killed = true;
                        results.Add(r);
                        return results;
                    }
                }
                else
                {
                    r.evaded = true;                    
                }
                results.Add(r);
                if (attacker.CanDoubleAttack(defender))
                {                    
                    attackProb = attacker.GetHitRate(defender);
                    r = new BattleResult(attackerStatus, defenderStatus);
                    r.doubled = true;
                    if (Game.RNG.Pass(attackProb))
                    {
                        int damage = attacker.GetDamage(defender);
                        int critChance = attacker.GetCriticalChance(defender);

                        if (Game.RNG.Pass(critChance))
                        {
                            damage *= 3;
                            r.critical = true;
                        }
                        r.damage = damage;
                        defenderStatus.DoDamage(damage);

                        if (defenderStatus.IsDead)
                        {
                            r.killed = true;
                            results.Add(r);
                            return results;
                        }
                    }
                    else
                    {
                        r.evaded = true;                        
                    }
                    results.Add(r);
                }
                if (defender.CanDoubleAttack(attacker))
                {
                    defendProb = defender.GetHitRate(attacker);
                    r = new BattleResult(defenderStatus, attackerStatus);
                    if (Game.RNG.Pass(defendProb))
                    {
                        int damage = defender.GetDamage(attacker);
                        int critChance = defender.GetCriticalChance(attacker);

                        if (Game.RNG.Pass(critChance))
                        {
                            damage *= 3;
                            r.critical = true;
                        }
                        r.damage = damage;
                        attackerStatus.DoDamage(damage);

                        if (attackerStatus.IsDead)
                        {
                            r.killed = true;
                            results.Add(r);
                            return results;
                        }
                    }
                    else
                    {
                        r.evaded = true;                        
                    }
                    results.Add(r);
                }
                return results;
            }
        }
    }
}
